require 'byebug'

module Packer2D
  class Rect
    attr_accessor :x, :y, :width, :height
    attr_reader :acreage

    def initialize(x = 0, y = 0, width, height)
      @x, @y, @width, @height = x, y, width, height
      @acreage = @width * @height
    end

    def <=>(other)
      result = acreage <=> other.acreage
      result = height <=> other.height if result.zero?
      result
    end
  end

  class Cargo < Rect; end

  class Wrapper < Rect
    attr_accessor :right, :down, :used

    def initialize(x = 0, y = 0, width, height)
      super(x, y, width, height)
      @used = false
    end

    def include?(cargo)
      (width >= cargo.width) && (height >= cargo.height)
    end

    def find(cargo)
      if used
        right.find(cargo) || down.find(cargo)
      elsif include?(cargo)
        self
      else
        nil
      end
    end

    def split(cargo)
      @used = true
      @right = self.class.new(x + cargo.width, y, width - cargo.width, cargo.height)
      @down = self.class.new(x, y + cargo.height, width, height - cargo.height)
      cargo.x, cargo.y = x, y
    end

    def fit(cargos)
      cargos.sort! {|current, prev| prev <=> current}
      cargos.each do |cargo|
        return nil unless wrap = find(cargo)
        wrap.split(cargo)
      end
      cargos
    end
  end
end
